package compilationunit;

import java.util.Vector;
import java.util.Stack;
import java.util.StringTokenizer;

public class EntradaTabla{
//comun
private String id;
private char tipo;//¿¿¿'u' no adjudicado???,'i' entero, 'c' constante entera, 's' cadena,
                  //'v' vector,'f' funcion,'p' palabra reservada, 't' temporal
                  //'n' void.
private int tamano;//tamaño
private int linea;
//--------------
private int valor;//¿¿¿valor del entero???
private String lexema;
private int numargufuncion;
private char tipoargufuncion[];
private int valorretornofuncion; //0 VOID, 1 int
private int desplazamiento;
private boolean inicializado;
private Stack pilaArgumentos;
private boolean returnConValor;
private boolean esTipoReturn;
private String etiqueta;
private String temporal;
private String direccion;
private int espalabrareservada;//0 no es, 1 si es;



    public EntradaTabla(char tipo){
        this.tipo = tipo;
        pilaArgumentos = new Stack();
        valorretornofuncion = -1;
        tamano = -1;
        desplazamiento = -1;
        returnConValor = false;
        inicializado = false;
        esTipoReturn = false;
    }

    public EntradaTabla(String nombre, char tipo){
        id = nombre;
        this.tipo = tipo;
        returnConValor = false;
        valorretornofuncion = -1;
        tamano = -1;
        pilaArgumentos = new Stack();
        desplazamiento = -1;
        inicializado = false;
        esTipoReturn = false;
    }

    public EntradaTabla(String nombre, int linea){
        id = nombre;
        this.linea = linea;
        tipo = 'u';
        returnConValor = false;
        valorretornofuncion = -1;
        tamano = -1;
        pilaArgumentos = new Stack();
        desplazamiento = -1;
        inicializado = false;
        esTipoReturn = false;
    }

    public boolean tieneArgumentosIndefinidos(){
        if(id != null){
            if(id.indexOf("u") == -1)
                return false;
            else
                return true;
        }
        return false;
    }

    public void cambiarTipo(char tipo){
        this.tipo = tipo;
    }

    public String consultarSimbolo(){
        return id;
    }

    public void insertarIdentificador(String id){
        this.id = id;
    }

    public void aumentarNumArguFuncion(){
        numargufuncion++;
    }

    public int insertarTipo(char tipo){
        if (this.tipo == 'u'){
            this.tipo=tipo;
            return 0;
        }else{
            return -1;//ya estaba adjudicado el tipo
        }
    }

    public char consultarTipo(){
        return tipo;
    }

    public String mostrarTipo(){
        switch(tipo){
            case 'u':return "indefinido";
            case 'c':return "constante entera";
            case 'i':return "entero";
            case 's':return "cadena de caracteres";
            case 'v':return "vector";
            case 'f':return "funcion";
            case 'p':return "palabra reservada";
            case 't':return "temporal";
            default:return "ERROR FATAL: SIMBOLO CON TIPO NO CONTEMPLADO";
        }
    }

    public int insertarTamano(int tamano){
        this.tamano = tamano;
        if(tamano < 0)
            return -1;
        else
            return 0;
    }

    public int consultarTamano(){
        return tamano;
    }

    public int insertarValorEntero(int valor){

        if (tipo=='i' || tipo=='c'){
            this.valor=valor;
            return 0;
        }else{
            return -2;//no es un entero
        }
    }

    public void insertarValorEnteroIni(int valor){
           this.valor=valor;
    }

    public int consultarValorEntero(){
        return valor;
    }

    public int insertarLexema(String lexema){
    if (tipo=='s'){
        this.lexema=lexema;
        return 0;
    }else{
        return -3;//no es de l tipo cadena
    }
    }

    public String consultarLexema(){
        return lexema;
    }

    public void insertarNumArguFunc(int arg){
        numargufuncion=arg;
        if (tipo=='f'){
            tipoargufuncion = new char[arg];
        }
    }

    public int consultarNumArguFunc(){
        return numargufuncion;
    }

    public int insertarTipoArguFuncion(int lugar, char valor){
        if (lugar < numargufuncion){
            tipoargufuncion[lugar]=valor;
            return 0;
        }else{
            return -4;//error en el tamaño de la lista
        }
    }

    public char consultarTipoArguFuncion(int lugar){
        if (lugar < numargufuncion){
            return tipoargufuncion[lugar];
        }else{
            return 'e';//error en el tamaño de la lista
        }
    }

    public int insertarTipoReturn (int retorno){
        if (tipo != 'f'){
            return -1;
        }else{
            valorretornofuncion = retorno;
            return 0;
        }
    }

    public int consultarReturn(){
        return valorretornofuncion;
    }

    public void insertarLinea(int lin){
        linea = lin;
    }

    public int consultarLinea(){
        return linea;
    }

    public void insertarEsPalabraReservada(){
        espalabrareservada = 1;
    }

    public int consultarEsPalabraReservada(){
        return espalabrareservada;
    }

    public boolean generarIdentificadorFuncion(){
        if(tipo == 'f'){
            id += "(";
            for(int i=0; i < numargufuncion ;i++)
                if(i == (numargufuncion - 1))
                    id += (tipoargufuncion[i] == 'c'? 'i':tipoargufuncion[i]);
                else
                    id += (tipoargufuncion[i] == 'c'? 'i':tipoargufuncion[i]) + ",";
            id +=")";
            return true;
        }
        return false;
    }

    public boolean generarIdentificadorFuncionReverso(){
    Character tipoAct = null;
        if(tipo == 'f'){
            id += "(";
            tipoargufuncion = new char[numargufuncion];
            int i = 0;
            while(!pilaArgumentos.isEmpty())
            {
                tipoAct = (Character)pilaArgumentos.pop();
                if(tipoAct.charValue() == 'c')
                    tipoargufuncion[i] = 'i';
                else
                    tipoargufuncion[i] = tipoAct.charValue();
                i++;
                if(pilaArgumentos.isEmpty())
                    id += (tipoAct.charValue()=='c'?'i':tipoAct.charValue());
                else
                    id += (tipoAct.charValue()=='c'?'i':tipoAct.charValue()) + ",";
            }
            id +=")";
            return true;
        }
        return false;
    }

    public void insertarEnPila(char tipo){
        pilaArgumentos.push(new Character(tipo));
    }

    public void imprimirSimbolo(){
    System.out.print("id=");
    System.out.println(id);
    System.out.print("tipo=");
    System.out.println(tipo);
    System.out.print("tamano=");
    System.out.println(tamano);
    System.out.print("linea=");
    System.out.println(linea);
    System.out.print("valor=");
    System.out.println(valor);
    System.out.print("lexema=");
    System.out.println(lexema);
    System.out.print("listavector=");
    System.out.println("");
    System.out.print("numeros argumentos de funcion=");
    System.out.println(numargufuncion);
    System.out.print("tipoargufuncion=");
    System.out.println("");
    System.out.print("valor del retorno de funcion=");
    System.out.println(valorretornofuncion);
    System.out.print("espalabra reservada=");
    System.out.println(espalabrareservada);
    }

    public void imprimirSimbolo2() {
        System.out.print("id = " + id);
        System.out.print(" tipo = " + tipo);
        System.out.print(" linea = " + linea);
        System.out.print(" desplazamiento = " + desplazamiento);
        System.out.print(" etiqueta = " + etiqueta);
        if(tipo == 'v')System.out.print(" tamaño = " + tamano);
        if(tipo == 'c')System.out.print(" valor = " + valor);
        if(tipo == 's')System.out.print(" lexema = " + lexema);
        if(tipo == 'f')System.out.print(" retorno función = " + valorretornofuncion);
        System.out.println();
    }

    public void setPilaArgumentos(Stack pilaArgumentos) {
        this.pilaArgumentos = pilaArgumentos;
    }

    public Stack getPilaArgumentos() {
        return pilaArgumentos;
    }

    public void setReturnConValor(boolean returnConValor) {
        this.returnConValor = returnConValor;
    }

    public boolean isReturnConValor() {
        return returnConValor;
    }

    public void setDesplazamiento(int desplazamiento) {
        this.desplazamiento = desplazamiento;
        if(desplazamiento < 10)
            direccion = "0000000"+desplazamiento;
        else if(desplazamiento < 100)
            direccion = "000000"+desplazamiento;
        else if(desplazamiento < 1000)
            direccion = "00000"+desplazamiento;
        else if(desplazamiento < 10000)
            direccion = "0000"+desplazamiento;
        else if(desplazamiento < 100000)
            direccion = "000"+desplazamiento;
        else if(desplazamiento < 1000000)
            direccion = "00"+desplazamiento;
        else if(desplazamiento < 10000000)
            direccion = "0"+desplazamiento;
        else
            direccion = String.valueOf(desplazamiento);
    }

    public int getDesplazamiento() {
        return desplazamiento;
    }

    public void setInicializado(boolean inicializado) {
        this.inicializado = inicializado;
    }

    public boolean isInicializado() {
        return inicializado;
    }

    public void setEtiqueta(String etiqueta) {
        this.etiqueta = etiqueta;
    }

    public String getEtiqueta() {
        return etiqueta;
    }

    public void setTemporal(String temporal) {
        this.temporal = temporal;
    }

    public String getTemporal() {
        return temporal;
    }

    public void setDireccion(String direccion) {
        this.direccion = direccion;
    }

    public String getDireccion() {
        return direccion;
    }
    public String mostrarIdentificadorFuncionError(){
        String result = null, auxiliar = null;
        StringTokenizer st = null;
        if(id.indexOf("()") != -1)
            return id;
        try{
        st = new StringTokenizer(id,"(",true);
        result = st.nextToken();
        auxiliar = st.nextToken(")");
        auxiliar += ")";
        //System.err.println("auxiliar vale " + auxiliar);
        for (int i=0 ; i < auxiliar.length() ; i++ )  {
            if(auxiliar.substring(i,i+1).equals("i"))
                result += "int";
            else if(auxiliar.substring(i,i+1).equals("v"))
                result += "int[]";
            else
                result += auxiliar.substring(i,i+1);
        }
        }catch(Exception e){ System.err.println("EXCEPCIÓN GENERANDO MENSAJES DE ERROR EN mostrarIdentificadorFuncionError()"); }
        return result;
    }

    public void setEsTipoReturn(boolean esTipoReturn) {
        this.esTipoReturn = esTipoReturn;
    }

    public boolean isEsTipoReturn() {
        return esTipoReturn;
    }
}

